/******************************************************************************
 * FileName:    gwin_spec.c
 * Desc:        上报接口
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

/*-------------------------- Includes ---------------------------------------*/
#include "gwin_global_config.h"

#include "gwin_spec.h"
#include "gwin_protocol_task.h"


/*-------------------------- Macro Definitions ------------------------------*/
#define LOCAL_DEBUG_EN                      ( 0 )
#if LOCAL_DEBUG_EN
#define GWIN_DEBUG(...)                     USER_DEBUG(__VA_ARGS__)
#else
#define GWIN_DEBUG(...)
#endif


/*-------------------------- Type Declarations ------------------------------*/

/*-------------------------- Global Variables -------------------------------*/

/*-------------------------- Local Variables --------------------------------*/

/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
/**
 * @brief 属性上报
 */
uint8_t gwin_spec_property_changed(uint16_t siid, uint16_t piid, uint8_t data_type, uint32_t value)
{
    float value_f = 0;
    const char *value_str = NULL;

    if (data_type == DATA_TYPE_F32)
    {
        memcpy(&value_f, &value, sizeof(value_f));
        GWIN_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value = %f", siid, piid, data_type, value_f);
    }
    else if (data_type == DATA_TYPE_STRING)
    {
        value_str = (const char *)value;
        GWIN_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value_str = %s", siid, piid, data_type, value_str);
        if (strlen(value_str) <= 0)     // SDK处理空字符串，会出错断连
        {
            GWIN_DEBUG("str is NULL\n");
            return 1;
        }
    }
    else
    {
        GWIN_DEBUG("siid = %d, piid = %d, data_type = 0x%02x, value = %d", siid, piid, data_type, value);
    }

    uint8_t ret = 1;
    property_value_t *property_value = NULL;

    switch (data_type)
    {
        case DATA_TYPE_BOOL:
            property_value = property_value_new_boolean(value);
            break;

        case DATA_TYPE_U8:
            property_value = property_value_new_uchar(value);
            break;
        case DATA_TYPE_U16:
            property_value = property_value_new_ushort(value);
            break;
        case DATA_TYPE_U32:
            property_value = property_value_new_ulong(value);
            break;

        case DATA_TYPE_I8:
            property_value = property_value_new_char(value);
            break;
        case DATA_TYPE_I16:
            property_value = property_value_new_short(value);
            break;
        case DATA_TYPE_I32:
            property_value = property_value_new_long(value);
            break;

        case DATA_TYPE_F32:
            property_value = property_value_new_float(value_f);
            break;

        case DATA_TYPE_STRING:
            property_value = property_value_new_string(value_str);
            break;

        default:
            ret = 0;
            GWIN_DEBUG("Error : data_type = %d!!!", data_type);
            break;
    }

    if (ret)
    {
        if (miio_properties_changed(siid, piid, property_value) != 0)
        {
            ret = 0;
            GWIN_DEBUG("Error : send_property_changed failed!!!");
        }
    }

    return ret;
}

/**
 * @brief 事件上报
 */
void gwin_spec_event_occurred(uint16_t siid, uint16_t eiid, uint16_t piid_event, uint8_t data_type, uint32_t value)
{
    float value_f = 0;
    if (data_type == DATA_TYPE_F32)
    {
        memcpy(&value_f, &value, sizeof(value_f));
        GWIN_DEBUG("siid = %d, eiid = %d, data_type = 0x%02x, value = %f", siid, eiid, data_type, value_f);
    }
    else
    {
        GWIN_DEBUG("siid = %d, eiid = %d, data_type = 0x%02x, value = %d", siid, eiid, data_type, value);
    }

    // 初始化参数列表
    arguments_t * newArgs = arguments_new();
    if (newArgs == NULL)
    {
        GWIN_DEBUG("Error : arguments_new failed!!!");
        return;
    }

    // 参数个数
    if (data_type == DATA_TYPE_NONE)
    {
        newArgs->size = 0;
    }
    else
    {
        newArgs->size = 1;

        // 第0个参数: NULL
        newArgs->arguments[0].piid = piid_event;
        switch (data_type)
        {
            case DATA_TYPE_BOOL:
                newArgs->arguments[0].value = property_value_new_boolean(value);
                break;

            case DATA_TYPE_U8:
                newArgs->arguments[0].value = property_value_new_uchar(value);
                break;
            case DATA_TYPE_U16:
                newArgs->arguments[0].value = property_value_new_ushort(value);
                break;
            case DATA_TYPE_U32:
                newArgs->arguments[0].value = property_value_new_ulong(value);
                break;

            case DATA_TYPE_I8:
                newArgs->arguments[0].value = property_value_new_char(value);
                break;
            case DATA_TYPE_I16:
                newArgs->arguments[0].value = property_value_new_short(value);
                break;
            case DATA_TYPE_I32:
                newArgs->arguments[0].value = property_value_new_long(value);
                break;

            case DATA_TYPE_F32:
                newArgs->arguments[0].value = property_value_new_float(value_f);
                break;

            default:
                GWIN_DEBUG("Error : data_type = %d!!!", data_type);
                return;
        }
    }

    // 发送消息到服务器
    if (miio_event_occurred(siid, eiid, newArgs) != 0)
    {
        GWIN_DEBUG("Error : send_event_occurred failed!!!");
    }
}

/**
 * @brief 属性写
 */
void _gwin_spec_on_property_set(property_operation_t *o, uint16_t aiid)
{
    GWIN_DEBUG("siid = %d, piid = %d, format = %d", o->siid, o->piid, o->value->format);

    if (o->value == NULL)
    {
        o->code = OPERATION_ERROR_VALUE;
        GWIN_DEBUG("value is NULL\n");
        return;
    }

    o->code = OPERATION_OK;
    gwin_spec_unit_t spec_uint = { 0x00 };
    spec_uint.siid = o->siid;
    spec_uint.ea_iid = ((aiid > 0) ? aiid : GWIN_SPEC_PEA_IID_NONE);
    spec_uint.piid = o->piid;
    switch (o->value->format)
    {
        // LIN MARK 20240221 : MHCWB11S SDK，uint8、uint16、uint32、int8、int16、int32 数据类型，统一使用 int32 方式解析通讯。
        case PROPERTY_FORMAT_NUMBER:
            spec_uint.data_type = DATA_TYPE_I32;
            spec_uint.value = o->value->data.number.integerValue;
            break;

        case PROPERTY_FORMAT_BOOL:
            spec_uint.data_type = DATA_TYPE_BOOL;
            spec_uint.value = o->value->data.boolean;
            break;

        case PROPERTY_FORMAT_UCHAR:
            spec_uint.data_type = DATA_TYPE_U8;
            spec_uint.value = o->value->data.number.ucharValue;
            break;
        case PROPERTY_FORMAT_USHORT:
            spec_uint.data_type = DATA_TYPE_U16;
            spec_uint.value = o->value->data.number.ushortValue;
            break;
        case PROPERTY_FORMAT_ULONG:
            spec_uint.data_type = DATA_TYPE_U32;
            spec_uint.value = o->value->data.number.ulongValue;
            break;

        case PROPERTY_FORMAT_CHAR:
            spec_uint.data_type = DATA_TYPE_I8;
            spec_uint.value = o->value->data.number.charValue;
            break;
        case PROPERTY_FORMAT_SHORT:
            spec_uint.data_type = DATA_TYPE_I16;
            spec_uint.value = o->value->data.number.shortValue;
            break;
        case PROPERTY_FORMAT_LONG:
            spec_uint.data_type = DATA_TYPE_I32;
            spec_uint.value = o->value->data.number.longValue;
            break;

        case PROPERTY_FORMAT_FLOAT:
            spec_uint.data_type = DATA_TYPE_F32;
            memcpy(&spec_uint.value, (const void *)&o->value->data.number.floatValue, sizeof(spec_uint.value));
            break;

        case PROPERTY_FORMAT_STRING:
            spec_uint.data_type = DATA_TYPE_STRING;
            spec_uint.len = o->value->data.string.length;
            spec_uint.value = (uint32_t)o->value->data.string.value;
            GWIN_DEBUG("len = %d, data = %s", o->value->data.string.length, o->value->data.string.value);
            break;

        default:
            o->code = OPERATION_ERROR_VALUE;
            break;
    }

    if (o->code == OPERATION_OK)
    {
        GWIN_DEBUG("siid = %d, piid = %d, value = %d", spec_uint.siid, spec_uint.piid, spec_uint.value);
        gwin_protocol_data_recv(PROTOCOL_TASK_DATA_WAY_SPEC_SET, (uint8_t *)&spec_uint, sizeof(gwin_spec_unit_t));
    }
}
void gwin_spec_on_property_set(property_operation_t *o)
{
    _gwin_spec_on_property_set(o, 0);
}

/**
 * @brief 属性读
 */
void gwin_spec_on_property_get(property_operation_t *o)
{
//    GWIN_DEBUG("siid = %d, piid = %d, format = %d", o->siid, o->piid, o->value->format);    // 后台get属性点不带数据类型！！！
    GWIN_DEBUG("siid = %d, piid = %d", o->siid, o->piid);

    gwin_spec_unit_t spec_uint = { 0x00 };
    spec_uint.siid = o->siid;
    spec_uint.ea_iid = GWIN_SPEC_PEA_IID_NONE;
    spec_uint.piid = o->piid;

    gwin_get_spec((uint32_t)&spec_uint);
    float value_f = 0;
    const char *value_str = NULL;
    if (spec_uint.data_type == DATA_TYPE_F32)
    {
        memcpy(&value_f, &spec_uint.value, sizeof(value_f));
        GWIN_DEBUG("data_type = 0x%02x, value = %f", spec_uint.data_type, value_f);
    }
    else if (spec_uint.data_type == DATA_TYPE_STRING)
    {
        value_str = (const char *)spec_uint.value;
        GWIN_DEBUG("data_type = 0x%02x, value_str = %s", spec_uint.data_type, value_str);
        if (strlen(value_str) <= 0)     // SDK处理空字符串，会出错断连
        {
            o->code = OPERATION_ERROR_VALUE;
            GWIN_DEBUG("str is NULL\n");
            return;
        }
    }
    else
    {
        GWIN_DEBUG("data_type = 0x%02x, value = %d", spec_uint.data_type, spec_uint.value);
    }

    switch (spec_uint.data_type)
    {
        case DATA_TYPE_BOOL:
            o->value = property_value_new_boolean(spec_uint.value);
            break;

        case DATA_TYPE_U8:
            o->value = property_value_new_uchar(spec_uint.value);
            break;
        case DATA_TYPE_U16:
            o->value = property_value_new_ushort(spec_uint.value);
            break;
        case DATA_TYPE_U32:
            o->value = property_value_new_ulong(spec_uint.value);
            break;

        case DATA_TYPE_I8:
            o->value = property_value_new_char(spec_uint.value);
            break;
        case DATA_TYPE_I16:
            o->value = property_value_new_short(spec_uint.value);
            break;
        case DATA_TYPE_I32:
            o->value = property_value_new_long(spec_uint.value);
            break;

        case DATA_TYPE_F32:
            o->value = property_value_new_float(value_f);
            break;

        case DATA_TYPE_STRING:
            o->value = property_value_new_string(value_str);
            break;

        default:
            o->code = OPERATION_ERROR_VALUE;
            GWIN_DEBUG("value is NULL\n");
            return;
    }
}

/**
 * @brief 动作
 */
void gwin_spec_on_action_invoke(action_operation_t *o)
{
    GWIN_DEBUG("siid = %d, aiid = %d, in = %d, out = %d\n", o->siid, o->aiid, o->in->size, o->out->size);

    // 方法+参数，暂时只支持1个参数
    if (o->in->size >= 1)
    {
        property_operation_t property_operation = { 0x00 };
        memset(&property_operation, 0x00, sizeof(property_operation_t));
        property_operation.siid = o->siid;
        property_operation.piid = o->in->arguments[0].piid;
        property_operation.value = o->in->arguments[0].value;
        _gwin_spec_on_property_set(&property_operation, o->aiid);
    }
    // 常规情况
    else
    {
        gwin_spec_unit_t spec_uint = { 0x00 };
        spec_uint.siid = o->siid;
        spec_uint.ea_iid = o->aiid;
        spec_uint.piid = GWIN_SPEC_PEA_IID_NONE;
        spec_uint.data_type = DATA_TYPE_NONE;
        gwin_protocol_data_recv(PROTOCOL_TASK_DATA_WAY_SPEC_ACT, (uint8_t *)&spec_uint, sizeof(gwin_spec_unit_t));
    }
}


/*-------------------------- END OF FILE ------------------------------------*/

